// 1. 基准地址维护
// 2. 携带请求参数处理
// 3. 设置token
// 4. 提供常用请求方式调用api

import http from '@ohos.net.http'
import router from '@ohos.router'
import promptAction from '@ohos.promptAction'
import { Auth } from './Auth'
import { Logger } from './Logger'

const BASE_URL = 'https://api-harmony-teach.itheima.net/hm/'

const req = http.createHttp()

const request = <T = unknown>(url: string, method: http.RequestMethod = http.RequestMethod.GET, params: object = {}) => {
  let fullUrl = BASE_URL + url

  // 一些配置
  const options: http.HttpRequestOptions = {
    header: {
      'Content-Type': 'application/json',
    },
    readTimeout: 30000,
    method,
  }

  // 处理请求参数
  // 如果是对象数据拼接URL，如果是其他则携带在 extraData
  if (method === http.RequestMethod.GET) {
    const urlParams = Object.keys(params).map(key => `${key}=${params[key]}`)
    fullUrl += `?${urlParams.join('&')}`
  } else {
    options.extraData = params
  }

  // 携带token
  const user = Auth.getUser()
  if (user.token) {
    options.header['Authorization'] = `Bearer ${user.token}`
  }

  // 请求日志
  Logger.info(`REQUEST→${url}→${method}`, JSON.stringify(params))

  return req.request(fullUrl, options)
    .then(res => {
      // 成功
      // 响应日志
      Logger.info(`RESPONSE→${url}→${method}`, res.result.toString().substring(0, 250))
      if (res.result) {
        // 1. 处理响应
        const response = JSON.parse(res.result as string) as {
          code: number
          message: string
          data: T
        }
        if (response.code === 10000) {
          return response
        }
        // 2. 处理 token 失效
        if (response.code === 401) {
          Auth.delUser()
          // 如果多个接口报 401，只可跳转 LoginPage 一次
          router.pushUrl({
            url: 'pages/Login'
          }, router.RouterMode.Single)
          // 如果页面栈中已存在 LoginPage，将不再新增页面栈，而是把 LoginPage 放在最顶部
        }
      }
      // 没有响应数据 | 业务状态码错误 - 失败
      return Promise.reject(res.result)
    })
    .catch(err => {
      // 失败
      // 错误日志
      Logger.error(`RESPONSE→${url}→${method}`, JSON.stringify(err).substring(0, 250))
      promptAction.showToast({ message: '网络错误' })
      return Promise.reject(err)
    })
    .finally(() => {
      // 销毁请求释放资源
      req.destroy()
    })
}

export class Request {
  static get<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.GET, params)
  }

  static post<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.POST, params)
  }

  static put<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.PUT, params)
  }

  static delete<T>(url: string, params?: object) {
    return request<T>(url, http.RequestMethod.DELETE, params)
  }
}